from tkinter import *
from tkinter.ttk import *
import tkinter.messagebox as messageBox
import time
import re
import sys
from ...utils.utils import singleton
from ...utils.loggers import dev_logger,  record_logger
from ..uds_ui.models.modle_base_can import FunctestTemplate_Can
from ...globals import GLOBAL_UDS_SERVE_FUNC_LIB


@singleton
class SeatTest:
    def __init__(self, masterUI, parentWin: FunctestTemplate_Can) -> None:
        # 全局master实例
        self.masterUI = masterUI
        self.parentWin = parentWin

        # 初始操作主窗口
        self.initMaster()
        # 当前窗口实例
        self.initCurWindow()

    def initMaster(self):
        self.masterUI.withdraw()

    def initCurWindow(self):
        self.curWindow = Toplevel(self.masterUI)
        self.curWindow.geometry('900x800+600+200')
        self.curWindow.title('座椅测试操作台')

        self.initUserWindowFrame1()
        self.initUserWindowFrame2()
        self.initUserWindowFrame3()
        self.initUserWindowFrame6()

        # 启动程序时让vin码输入框自动获取焦点
        self.curVinCodeEntry.focus_set()
        pass

    def initUserWindowFrame1(self):
        '''
            VIN 输入框Frame
        '''

        # 本地函数
        if 1:
            # [x]: 后期改为扫码获取值,与OBD读取值得比对
            def validateVinCode():
                # Vin码输入框验证函数
                curVin = self.curVinCode.get()
                # print(f'validate VinCode {curVin}')

                # [x]: 待开启VIN匹配功能
                pat = re.compile(r'^LNB\w{8}\d{6}$')
                if pat.match(curVin):
                    # if len(curVin) > 4:

                    self.userWindowFrame2_1Btn1.configure(state='normal')
                    self.userWindowFrame2_1Btn2.configure(state='normal')
                    self.userWindowFrame2_1Btn3.configure(state='normal')
                    self.userWindowFrame2_1Btn4.configure(state='normal')
                    self.userWindowFrame2_1Btn5.configure(state='normal')
                    # self.userWindowFrame2_1Btn6.configure(state='normal')
                    self.userWindowFrame2_1Btn7.configure(state='normal')
                    # self.userWindowFrame2_1Btn8.configure(state='normal')

                    self.userWindowFrame3_Btn1.configure(state='normal')
                    self.userWindowFrame3_Btn2.configure(state='normal')
                    self.userWindowFrame3_Btn3.configure(state='normal')
                    return True

                else:
                    return False

            def validateVinCodeFailed():
                self.userWindowFrame2_1Btn1.configure(state='disabled')
                self.userWindowFrame2_1Btn2.configure(state='disabled')
                self.userWindowFrame2_1Btn3.configure(state='disabled')
                self.userWindowFrame2_1Btn4.configure(state='disabled')
                self.userWindowFrame2_1Btn5.configure(state='disabled')
                # self.userWindowFrame2_1Btn6.configure(state='disabled')
                self.userWindowFrame2_1Btn7.configure(state='disabled')
                # self.userWindowFrame2_1Btn8.configure(state='disabled')

                messageBox.showwarning('VIN码验证警告', 'VIN码验证不通过，请核对输入的VIN码是否正确？')
                # print('validate failed...')
                pass

            def curVinCodeGet():
                # 清理输入框内容，获取焦点
                self.curVinCodeEntry.delete(0, END)
                self.curVinCodeEntry.focus_set()

                def get_vin():
                    '''
                        读取车身vin，并写入到entry中
                    '''
                    try:
                        vin_response = GLOBAL_UDS_SERVE_FUNC_LIB.serve_22_f190()
                        vin_list = vin_response.response.param[2:]
                        vin_str = "".join(
                            [f"{chr(item)}" for item in vin_list])
                        print(f'[file:{__file__}]=>[line:{
                            (sys._getframe().f_lineno)}]==>{vin_str}')

                        self.curVinCode.set(vin_str)

                    except:
                        messageBox.showwarning('读取vin出错了')
                        print(f'[file:{__file__}]=>[line:{
                            (sys._getframe().f_lineno)}]==>读取vin出错了...')

                get_vin()

                # 设置按钮使能
                # TODO: 后期将几个测试按钮的使能操作打包起来,或者用容器装起来,遍历实现可扩展性.
                self.userWindowFrame2_1Btn1.configure(state='disabled')
                self.userWindowFrame2_1Btn2.configure(state='disabled')
                self.userWindowFrame2_1Btn3.configure(state='disabled')
                self.userWindowFrame2_1Btn4.configure(state='disabled')
                self.userWindowFrame2_1Btn5.configure(state='disabled')
                # self.userWindowFrame2_1Btn6.configure(state='disabled')
                self.userWindowFrame2_1Btn7.configure(state='disabled')
                # self.userWindowFrame2_1Btn8.configure(state='disabled')

                self.userWindowFrame3_Btn1.configure(state='disabled')
                self.userWindowFrame3_Btn2.configure(state='disabled')
                self.userWindowFrame3_Btn3.configure(state='disabled')

                # [ ] 待确认,重置后是否把展示状态复位?
                for wediget in self.userWindowFrame2_1TestResMsg.values():
                    print('wdiget:', wediget)
                    wediget.configure(text='待检测...', foreground='gray')
                    # wediget.configure(foreground='gray')

        self.userWindowFrame1 = Frame(self.curWindow, relief='groove')
        self.userWindowFrame1.grid(
            row=1, column=1, columnspan=5, padx=20, pady=20)
        self.curVinCodeLabel = Label(self.userWindowFrame1, text='读取当前VIN码')
        self.curVinCodeLabel.grid(row=1, column=1, padx=10, pady=10)
        self.curVinCode = StringVar()
        self.curVinCode.set('LNB12341234123412')
        self.curVinCodeEntry = Entry(self.userWindowFrame1, textvariable=self.curVinCode,
                                     validate='focusout', validatecommand=validateVinCode, invalidcommand=validateVinCodeFailed)
        self.curVinCodeEntry.grid(row=1, column=2, padx=10, pady=10)
        self.curVinCodeConfirmBtn = Button(self.userWindowFrame1, text='确认')
        self.curVinCodeConfirmBtn.grid(row=1, column=3, padx=10, pady=10)
        self.curVinCodeResetBtn = Button(
            self.userWindowFrame1, text='读取车辆VIN', command=curVinCodeGet)
        self.curVinCodeResetBtn.grid(row=1, column=4, padx=10, pady=10)

    def initUserWindowFrame2(self):
        '''
            单个座椅测量按钮
        '''
        self.userWindowFrame2 = Frame(self.curWindow)
        self.userWindowFrame2.grid(
            row=2, column=1, columnspan=5, padx=20, pady=20)
        if 1:
            self.userWindowFrame2_1 = Frame(
                self.userWindowFrame2, relief='groove')
            self.userWindowFrame2_1.grid(row=1, column=1)
            # TODO: 后期改成遍历循环模式
            if 1:
                self.userWindowFrame2_1TestResMsg = {}
                self.userWindowFrame2_1Btn1 = Button(
                    self.userWindowFrame2_1, state=DISABLED, text='主驾按摩', command=self.seatUnittest('00'))
                self.userWindowFrame2_1Btn1.grid(
                    row=1, column=1, padx=10, pady=10)
                self.userWindowFrame2_1TestResMsg['00'] = Message(
                    self.userWindowFrame2_1, width=200, foreground='gray', text='主驾按摩测试结果')
                self.userWindowFrame2_1TestResMsg['00'].grid(
                    row=1, column=2, padx=10, pady=10)
                self.userWindowFrame2_1Btn2 = Button(
                    self.userWindowFrame2_1, state=DISABLED, text='副驾按摩', command=self.seatUnittest('01'))
                self.userWindowFrame2_1Btn2.grid(
                    row=1, column=3, padx=10, pady=10)
                self.userWindowFrame2_1TestResMsg['01'] = Message(
                    self.userWindowFrame2_1, width=200, foreground='gray', text='副驾按摩测试结果')
                self.userWindowFrame2_1TestResMsg['01'].grid(
                    row=1, column=4, padx=10, pady=10)
                self.userWindowFrame2_1Btn3 = Button(
                    self.userWindowFrame2_1, state=DISABLED, text='左后按摩', command=self.seatUnittest('02'))
                self.userWindowFrame2_1Btn3.grid(
                    row=2, column=1, padx=10, pady=10)
                self.userWindowFrame2_1TestResMsg['02'] = Message(
                    self.userWindowFrame2_1, width=200, foreground='gray', text='左后按摩测试结果')
                self.userWindowFrame2_1TestResMsg['02'].grid(
                    row=2, column=2, padx=10, pady=10)
                self.userWindowFrame2_1Btn4 = Button(
                    self.userWindowFrame2_1, state=DISABLED, text='右后按摩', command=self.seatUnittest('03'))
                self.userWindowFrame2_1Btn4.grid(
                    row=2, column=3, padx=10, pady=10)
                self.userWindowFrame2_1TestResMsg['03'] = Message(
                    self.userWindowFrame2_1, width=200, foreground='gray', text='右后按摩测试结果')
                self.userWindowFrame2_1TestResMsg['03'].grid(
                    row=2, column=4, padx=10, pady=10)

                self.userWindowFrame2_1Btn5 = Button(
                    self.userWindowFrame2_1, state=DISABLED, text='主副驾通风加热', command=self.seatUnittest('10'))
                self.userWindowFrame2_1Btn5.grid(
                    row=3, column=1, padx=10, pady=10)
                self.userWindowFrame2_1TestResMsg['10'] = Message(
                    self.userWindowFrame2_1, width=200, foreground='gray', text='主副驾通风加热测试结果')
                self.userWindowFrame2_1TestResMsg['10'].grid(
                    row=3, column=2, padx=10, pady=10)

                # self.userWindowFrame2_1Btn6 = Button(
                #     self.userWindowFrame2_1, state=DISABLED, text='副驾通风加热', command=self.seatUnittest('11'))
                # self.userWindowFrame2_1Btn6.grid(
                #     row=3, column=3, padx=10, pady=10)
                # self.userWindowFrame2_1TestResMsg['11'] = Message(
                #     self.userWindowFrame2_1, width=200, foreground='gray', text='副驾通风加热测试结果')
                # self.userWindowFrame2_1TestResMsg['11'].grid(
                #     row=3, column=4, padx=10, pady=10)

                self.userWindowFrame2_1Btn7 = Button(
                    self.userWindowFrame2_1, state=DISABLED, text='后排通风加热', command=self.seatUnittest('12'))
                self.userWindowFrame2_1Btn7.grid(
                    row=4, column=1, padx=10, pady=10)
                self.userWindowFrame2_1TestResMsg['12'] = Message(
                    self.userWindowFrame2_1, width=200, foreground='gray', text='后排通风加热测试结果')
                self.userWindowFrame2_1TestResMsg['12'].grid(
                    row=4, column=2, padx=10, pady=10)

                # self.userWindowFrame2_1Btn8 = Button(
                #     self.userWindowFrame2_1, state=DISABLED, text='右后通风加热', command=self.seatUnittest('13'))
                # self.userWindowFrame2_1Btn8.grid(
                #     row=4, column=3, padx=10, pady=10)
                # self.userWindowFrame2_1TestResMsg['13'] = Message(
                #     self.userWindowFrame2_1, width=200, foreground='gray', text='右后通风加热测试结果')
                # self.userWindowFrame2_1TestResMsg['13'].grid(
                #     row=4, column=4, padx=10, pady=10)

    def initUserWindowFrame3(self):
        '''
            一键快检Frame
        '''

        # 增加一键快检功能
        self.userWindowFrame3 = Frame(self.curWindow, relief='groove')
        self.userWindowFrame3.grid(
            row=3, column=1, columnspan=5, padx=20, pady=20)

        # 本地函数
        if 1:
            # FIXME: 一键快检功能函数
            # [ ] 待确认几个按钮同时点击会否有异步运行问题
            def testLV3():
                self.userWindowFrame2_1Btn1.invoke()
                self.userWindowFrame2_1Btn2.invoke()

                self.userWindowFrame2_1Btn5.invoke()
                # self.userWindowFrame2_1Btn6.invoke()

            def testLV4():
                self.userWindowFrame2_1Btn1.invoke()
                self.userWindowFrame2_1Btn2.invoke()
                self.userWindowFrame2_1Btn3.invoke()
                self.userWindowFrame2_1Btn4.invoke()

                self.userWindowFrame2_1Btn5.invoke()
                # self.userWindowFrame2_1Btn6.invoke()
                self.userWindowFrame2_1Btn7.invoke()
                # self.userWindowFrame2_1Btn8.invoke()

            def testLV5():
                '''
                    与LV4相同,所以直接调用LV4的test
                '''
                testLV4()

        # 按钮布局
        if 1:
            self.userWindowFrame3_Label1 = Label(
                self.userWindowFrame3, text='一键快检')
            self.userWindowFrame3_Label1.grid(
                row=1, column=1, columnspan=3, padx=20, pady=20)
            self.userWindowFrame3_Btn1 = Button(
                self.userWindowFrame3, state=DISABLED, text='LV3', command=testLV3)
            self.userWindowFrame3_Btn1.grid(row=2, column=1, padx=20, pady=20)
            self.userWindowFrame3_Btn2 = Button(
                self.userWindowFrame3, state=DISABLED, text='LV4', command=testLV4)
            self.userWindowFrame3_Btn2.grid(row=2, column=2, padx=20, pady=20)
            self.userWindowFrame3_Btn3 = Button(
                self.userWindowFrame3, state=DISABLED, text='LV5', command=testLV5)
            self.userWindowFrame3_Btn3.grid(row=2, column=3, padx=20, pady=20)

    def initUserWindowFrame6(self):
        '''
            运行信息展示
        '''

        # 测试结果显示框
        self.userWindowFrame6 = Frame(self.curWindow)
        self.userWindowFrame6.grid(
            row=6, column=1, columnspan=5, padx=20, pady=20)
        if 1:

            self.userWindowFrame6recordListboxScroll = Scrollbar(
                self.userWindowFrame6, orient=VERTICAL)
            self.userWindowFrame6recordListboxScroll.grid(
                row=2, column=11, sticky="ns")
            self.userWindowFrame6recordListbox = Listbox(
                self.userWindowFrame6,
                font=("Arial", 12),
                height=10,
                width=80,
                yscrollcommand=self.userWindowFrame6recordListboxScroll.set,
            )
            self.userWindowFrame6recordListbox.grid(
                row=2, column=0, columnspan=11, sticky="nw")
            self.userWindowFrame6recordListboxScroll.config(
                command=self.userWindowFrame6recordListbox.yview)
            self.userWindowFrame6recordClearBtn = Button(
                self.userWindowFrame6,
                text="清空测试记录",
                command=lambda: self.userWindowFrame6recordListbox.delete(
                    0, END),
            )
            self.userWindowFrame6recordClearBtn.grid(
                row=2, column=12, padx=2, pady=1)

    def seatUnittest(self, posId):
        # dev_logger.debug(f'seatUnittest running...{posId}.........')
        unitName = self.parentWin.can_unitTestmodelDict[posId].name
        dev_logger.debug(f'seatUnittest running...{
                         posId}....unitName:{unitName}.....')

        def callback(worker):

            record_logger.debug(f'seatUnittest  callback running ...{
                posId}.........')
            if 1:
                ret = worker.result()
                resFlag = ret.resFlag
                resString = ret.resString
                record_logger.debug(f'seatUnittest  callback running ...{
                    posId}...{resFlag, resString}.........')

                # userwindow中的信息展示
                self.userWindowFrame2_1TestResMsg[posId].configure(
                    text=resString)
                foreground = 'green' if resFlag else 'red'
                self.userWindowFrame2_1TestResMsg[posId].configure(
                    foreground=foreground)

                # 保留测试record信息
                recordStringLogger = f'VIN,{self.curVinCode.get():>17},{
                    resString}'
                record_logger.info(recordStringLogger)

                # 增加当前时间
                recordStringListobx = f'{time.strftime(
                    "%Y-%m-%d %H:%M:%S", time.localtime())}--{unitName}---{recordStringLogger}'
                # print('----',recordStr)
                self.userWindowFrame6recordListbox.insert(
                    'end', recordStringListobx)
                # 设置条目颜色
                if not resFlag:
                    self.userWindowFrame6recordListbox.itemconfig(
                        'end', background='pink')
                self.userWindowFrame6recordListbox.see(
                    self.userWindowFrame6recordListbox.size())
                # pass

        def wrapper():
            dev_logger.debug(f'seatUnittest  wrapper running ...{
                             posId}.........')
            # 点击按钮的测试结果结构是 resFlag,resString
            testResult = self.parentWin.unitTestCommand(posId)()
            testResult.add_done_callback(callback)

        return wrapper


def seat_test_window(masterUI, parentWin):
    '''
        座椅检测弹出窗口
    '''
    SeatTest(masterUI, parentWin)
